﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Threading;
using System.Collections;

using BEX;
using BEX.Core;
using BEX.Core.Exchange;
using BEX.RuleMonitor;
using BEX.DataAccess;



namespace TestHarness
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private UserAccount _current;

        private ExchangeMonitor _monitor;
        private RuleMonitor _ruleMonitor;

        private ArrayList _status = new ArrayList();

        public MainWindow()
        {
            InitializeComponent();

            Binding();
        }

        private void Binding()
        {
            dgAccountList.ItemsSource = UserAccount.GetList();

            cbExchange.ItemsSource = Enum.GetValues(typeof(ExchangeType)).Cast<ExchangeType>();
            cbExchange.SelectedIndex = 0;

            cbFlatExchange.ItemsSource = Enum.GetValues(typeof(ExchangeType)).Cast<ExchangeType>();
            cbFlatExchange.SelectedIndex = 0;

            cbIncrementExchange.ItemsSource = Enum.GetValues(typeof(ExchangeType)).Cast<ExchangeType>();
            cbIncrementExchange.SelectedIndex = 0;

            cbExchangeConfig.ItemsSource = Enum.GetValues(typeof(ExchangeType)).Cast<ExchangeType>();
            cbExchangeConfig.SelectedIndex = 0;
            cbArbExchangeA.ItemsSource = Enum.GetValues(typeof(ExchangeType)).Cast<ExchangeType>();
            cbArbExchangeB.ItemsSource = Enum.GetValues(typeof(ExchangeType)).Cast<ExchangeType>();
            cbArbCounterCurrency.ItemsSource = Enum.GetValues(typeof(CurrencyType)).Cast<CurrencyType>();

            SetFlatRuleBaseCurrency((ExchangeType)cbFlatExchange.SelectedValue);

            SetPercentRuleBaseCurrency((ExchangeType)cbExchange.SelectedValue);

            SetIncrementRuleBaseCurrency((ExchangeType)cbIncrementExchange.SelectedValue);

            cbCurrentAccount.ItemsSource = UserAccount.GetList();
            cbCurrentAccount.DisplayMemberPath = "EmailAddress";
            cbCurrentAccount.SelectedValuePath = "AccountID";
            cbCurrentAccount.SelectedIndex = 0;

            SetCurrentUser((int)cbCurrentAccount.SelectedValue);

            dgPercentRuleList.ItemsSource = PercentageRule.GetListForAccount(_current.AccountID);
            dgFlatRuleList.ItemsSource = FlatAmountRule.GetListForAccount(_current.AccountID);
            dgIncrementRuleList.ItemsSource = IncrementRule.GetListForAccount(_current.AccountID);
            dgArbRuleList.ItemsSource = ArbitrageRule.GetListForAccount(_current.AccountID);
        }

        private void buAddAccount_Click(object sender, RoutedEventArgs e)
        {
            var _u = new UserAccount();

            _u.EmailAddress = tbEmail.Text;
            _u.FirstName = tbFirst.Text;
            _u.LastName = tbLast.Text;
            _u.SmsRemaining = 0;

            _u.Save();

            dgAccountList.ItemsSource = null;
            dgAccountList.ItemsSource = UserAccount.GetList();
        }

        private void cbCurrentAccount_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetCurrentUser((int)cbCurrentAccount.SelectedValue);
        }

        protected void SetCurrentUser(int AcctID)
        {
            _current = UserAccount.Get(AcctID);
            lbStatus.Content = "User: " + _current.EmailAddress;
        }

        private void AddExchangeStatusTab(ExchangeType exch)
        {
            var _rb = new RichTextBox();

            _rb.Name = "rb" + exch.ToString();
            _rb.FlowDirection = System.Windows.FlowDirection.LeftToRight;
            _rb.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
            _rb.HorizontalContentAlignment = HorizontalAlignment.Left;
            _rb.IsReadOnly = true;
            _rb.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
            _rb.AcceptsReturn = false;
            _rb.VerticalContentAlignment = VerticalAlignment.Bottom;
            _rb.Height = 619;


            var _p = _rb.Document.Blocks.FirstBlock as Paragraph;
            _p.Margin = new Thickness(0);




            var _tb = new TabItem();
            _tb.Name = "tb" + exch.ToString();
            _tb.Header = exch.ToString();

            _tb.Content = _rb;


            tbStatus.Items.Add(_tb);

            _status.Add(_rb);
        }

        private void buStartListen_Click(object sender, RoutedEventArgs e)
        {
            _monitor = new ExchangeMonitor();

            
            if ((bool)cbUSD.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.USD });
            }

            if ((bool)cbGBP.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.GBP });
            }

            if ((bool)cbLTC.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.LTC, Counter = CurrencyType.USD });
            }
            if ((bool)cbEUR.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.EUR });
            }
            if ((bool)cbJPY.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.JPY });
            }
            if ((bool)cbCAD.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.CAD });
            }
            if ((bool)cbCHF.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.CHF });
            }
            if ((bool)cbRUB.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.RUB });
            }
            if ((bool)cbAUD.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.AUD });
            }
            if ((bool)cbSEK.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.SEK });
            }
            if ((bool)cbDKK.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.DKK });
            }
            if ((bool)cbHKD.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.HKD });
            }
            if ((bool)cbPLN.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.PLN });
            }
            if ((bool)cbCNY.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.CNY });
            }
            if ((bool)cbSGD.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.SGD });
            }
            if ((bool)cbTHB.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.THB });
            }
            if ((bool)cbNZD.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.NZD });
            }
            if ((bool)cbNOK.IsChecked)
            {
                _monitor.AddMonitoredCurrency(new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.NOK });
            }

            _monitor.MonitorBTCE = (bool)cbBTCE.IsChecked;

            if (_monitor.MonitorBTCE)
            {
                AddExchangeStatusTab(ExchangeType.BTCE);
            }
            _monitor.MonitorGox = (bool)cbGOX.IsChecked;

            if (_monitor.MonitorGox)
            {
                AddExchangeStatusTab(ExchangeType.MTGOX);
            }
            _monitor.MonitorCoinbase = (bool)cbCOINBASE.IsChecked;

            if (_monitor.MonitorCoinbase)
            {
                AddExchangeStatusTab(ExchangeType.COINBASE);
            }
            _monitor.MonitorBitstamp = (bool)cbBITSTAMP.IsChecked;


            if (_monitor.MonitorBitstamp)
            {
                AddExchangeStatusTab(ExchangeType.BITSTAMP);
            }
            _monitor.MonitorBitFinex = (bool)cbBITFINEX.IsChecked;


            if (_monitor.MonitorBitFinex)
            {
                AddExchangeStatusTab(ExchangeType.BITFINEX);
            }
            _monitor.MonitorTradehill = (bool)cbTRADEHILL.IsChecked;


            if (_monitor.MonitorTradehill)
            {
                AddExchangeStatusTab(ExchangeType.TRADEHILL);
            }
            _monitor.MonitorCampBX = (bool)cbCAMPBX.IsChecked;


            if (_monitor.MonitorCampBX)
            {
                AddExchangeStatusTab(ExchangeType.CAMPBX);
            }
            _monitor.OnUpdateStatus += _gox_OnUpdateStatus;
            _monitor.Listen();
        }

        protected void _gox_OnUpdateStatus(object sender, ProgressEventArgs e)
        {
            UpdateStatus(e.Status, e.Exchange);
        }

        private void UpdateStatus(string message, ExchangeType exch)
        {
            Action workAction = delegate
            {
                RichTextBox _toUpdate = null;

                foreach (RichTextBox _r in _status)
                {
                    if (_r.Name == "rb" + exch.ToString())
                    {
                        _toUpdate = _r;
                        break;
                    }
                }
                var rangeOfText1 = new TextRange(_toUpdate.Document.ContentEnd, _toUpdate.Document.ContentEnd);
                rangeOfText1.Text = message + Environment.NewLine;
                rangeOfText1.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
                rangeOfText1.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);

                if (_toUpdate.Document.Blocks.Count > 20)
                {
                    _toUpdate.Document.Blocks.Remove(_toUpdate.Document.Blocks.FirstBlock);
                }


                _toUpdate.ScrollToEnd();

            };

            System.Windows.Application.Current.Dispatcher.BeginInvoke(
            DispatcherPriority.Background,
               workAction);
        }

        protected void _ruleMonitor_OnUpdateStatus(object sender, RuleMonitorProgressEventArgs e)
        {
            UpdateRuleStatus(e.Status, e.Exchange);
        }

        private void UpdateRuleStatus(string message, ExchangeType exch)
        {
            Action workAction = delegate
            {

                var rangeOfText1 = new TextRange(rbRuleStatus.Document.ContentEnd, rbRuleStatus.Document.ContentEnd);
                rangeOfText1.Text = message + Environment.NewLine;
                rangeOfText1.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
                rangeOfText1.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                rbRuleStatus.ScrollToEnd();

                if (rbRuleStatus.Document.Blocks.Count > 40)
                {
                    rbRuleStatus.Document.Blocks.Remove(rbRuleStatus.Document.Blocks.FirstBlock);
                }

            };

            System.Windows.Application.Current.Dispatcher.BeginInvoke(
            DispatcherPriority.Background,
               workAction);
        }


        private void buStartRuleMonitor_Click(object sender, RoutedEventArgs e)
        {
            buStartRuleMonitor.IsEnabled = false;
            buStopRuleMonitor.IsEnabled = true;

            _ruleMonitor = new RuleMonitor();

            _ruleMonitor.OnUpdateStatus += _ruleMonitor_OnUpdateStatus;
            _ruleMonitor.Start();
        }

        private void buStopRuleMonitor_Click(object sender, RoutedEventArgs e)
        {

            _ruleMonitor.Stop();

            buStartRuleMonitor.IsEnabled = true;
            buStopRuleMonitor.IsEnabled = false;
        }

        private void buAddIncrementRule_Click(object sender, RoutedEventArgs e)
        {
            var _rule = new IncrementRule((ExchangeType)cbIncrementExchange.SelectedValue,
            (CurrencyType)cbIncrementBaseCurrency.SelectedValue,
            (CurrencyType)cbIncrementCounterCurrency.SelectedValue,
                                                    Convert.ToDecimal(tbIncrement.Text),
                                                    Convert.ToInt32(tbIncrementTimeSpan.Text));

            _rule.Save();

            _rule.AddAccount(_current.AccountID);

            dgIncrementRuleList.ItemsSource = null;
            dgIncrementRuleList.ItemsSource = IncrementRule.GetListForAccount(_current.AccountID);
        }

        private void buAddPercentRule_Click(object sender, RoutedEventArgs e)
        {
            var _rule = new PercentageRule((ExchangeType)cbExchange.SelectedValue, (CurrencyType)cbPercentBaseCurrency.SelectedValue, (CurrencyType)cbPercentCounterCurrency.SelectedValue, Convert.ToDecimal(tbPercent.Text), Convert.ToInt32(tbTimeSpan.Text));

            _rule.Save();

            _rule.AddAccount(_current.AccountID);

            dgPercentRuleList.ItemsSource = null;
            dgPercentRuleList.ItemsSource = PercentageRule.GetListForAccount(_current.AccountID);
        }

        private void buAddFlatRule_Click(object sender, RoutedEventArgs e)
        {
            var _rule = new FlatAmountRule((ExchangeType)cbFlatExchange.SelectedValue, (CurrencyType)cbFlatBaseCurrency.SelectedValue, (CurrencyType)cbFlatCounterCurrency.SelectedValue, Convert.ToInt32(Convert.ToDecimal(tbFlatAmount.Text) * global.ConversionFactor));

            _rule.Save();

            _rule.AddAccount(_current.AccountID);

            dgFlatRuleList.ItemsSource = null;
            dgFlatRuleList.ItemsSource = FlatAmountRule.GetListForAccount(_current.AccountID);
        }

        private void buAddArbRule_Click(object sender, RoutedEventArgs e)
        {


            var _rule = new ArbitrageRule((ExchangeType)cbArbExchangeA.SelectedValue, (ExchangeType)cbArbExchangeB.SelectedValue, new CurrencyPair() { Base = CurrencyType.BTC, Counter = (CurrencyType)cbArbCounterCurrency.SelectedValue }, Convert.ToDecimal(tbArbPercent.Text));

            _rule.Save();

            _rule.AddAccount(_current.AccountID);

            dgArbRuleList.ItemsSource = null;
            dgArbRuleList.ItemsSource = ArbitrageRule.GetListForAccount(_current.AccountID);
        }


        private void cbFlatExchange_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetFlatRuleBaseCurrency((ExchangeType)cbFlatExchange.SelectedValue);
            SetFlatRuleCounterCurrency((ExchangeType)cbFlatExchange.SelectedValue, (CurrencyType)cbFlatBaseCurrency.SelectedValue);
        }

        private void cbFlatBaseCurrency_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetFlatRuleCounterCurrency((ExchangeType)cbFlatExchange.SelectedValue, (CurrencyType)cbFlatBaseCurrency.SelectedValue);
        }

        private void cbExchange_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetPercentRuleBaseCurrency((ExchangeType)cbExchange.SelectedValue);
            SetPercentRuleCounterCurrency((ExchangeType)cbExchange.SelectedValue, (CurrencyType)cbPercentBaseCurrency.SelectedValue);
        }

        private void cbIncrementExchange_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetIncrementRuleBaseCurrency((ExchangeType)cbIncrementExchange.SelectedValue);
            SetIncrementRuleCounterCurrency((ExchangeType)cbIncrementExchange.SelectedValue, (CurrencyType)cbIncrementBaseCurrency.SelectedValue);
        }

        private void cbPercentBaseCurrency_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetPercentRuleCounterCurrency((ExchangeType)cbExchange.SelectedValue, (CurrencyType)cbPercentBaseCurrency.SelectedValue);
        }

        private void cbIncrementBaseCurrency_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SetIncrementRuleCounterCurrency((ExchangeType)cbIncrementExchange.SelectedValue, (CurrencyType)cbIncrementBaseCurrency.SelectedValue);
        }

        private void SetIncrementRuleCounterCurrency(ExchangeType type, CurrencyType basec)
        {
            cbIncrementCounterCurrency.ItemsSource = ExchangeDAL.GetSupportedCounterCurrencies(type, basec);
            cbIncrementCounterCurrency.SelectedIndex = 0;
        }

        private void SetIncrementRuleBaseCurrency(ExchangeType type)
        {
            cbIncrementBaseCurrency.ItemsSource = ExchangeDAL.GetSupportedBaseCurrencies(type);
            cbIncrementBaseCurrency.SelectedIndex = 0;
        }

        private void SetPercentRuleBaseCurrency(ExchangeType type)
        {
            cbPercentBaseCurrency.ItemsSource = ExchangeDAL.GetSupportedBaseCurrencies(type);
            cbPercentBaseCurrency.SelectedIndex = 0;
        }

        private void SetPercentRuleCounterCurrency(ExchangeType type, CurrencyType basec)
        {
            cbPercentCounterCurrency.ItemsSource = ExchangeDAL.GetSupportedCounterCurrencies(type, basec);
            cbPercentCounterCurrency.SelectedIndex = 0;
        }

        private void SetFlatRuleBaseCurrency(ExchangeType type)
        {
            cbFlatBaseCurrency.ItemsSource = ExchangeDAL.GetSupportedBaseCurrencies(type);
            cbFlatBaseCurrency.SelectedIndex = 0;
        }

        private void SetFlatRuleCounterCurrency(ExchangeType type, CurrencyType basec)
        {
            cbFlatCounterCurrency.ItemsSource = ExchangeDAL.GetSupportedCounterCurrencies(type, basec);
            cbFlatCounterCurrency.SelectedIndex = 0;
        }
    }
}
